package com.seven.webhook.component;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.seven.webhook.component.prometheus.PrometheusApiUtils;
import com.seven.webhook.model.bean.alertmanager.Alerts;
import com.seven.webhook.model.MonitorEmail;
import com.seven.webhook.model.MonitorRule;
import com.seven.webhook.service.IMailService;
import com.seven.webhook.service.MonitorEmailService;
import com.seven.webhook.service.MonitorRuleService;
import lombok.Data;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 初始化类
 * 自动备份任务初始化
 * 服务一启动 自动备份开始
 */
@Order(1) // @Order注解可以改变执行顺序，越小越先执行
@Component
@Slf4j
public class TaskRunnerComponent implements ApplicationRunner {

    @Autowired
    ScheduledFutureComponent scheduledFutureComponent;
    @Autowired
    MonitorRuleService monitorRuleService;
    @Autowired
    MonitorEmailService monitorEmailService;
    @Autowired
    IMailService iMailService;

    /**
     * 会在服务启动完成后立即执行
     */
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        try {
            log.info("初始化自动任务" + arg0);
            init();
        } catch (Exception e) {

        }
    }

    //告警计时器
    public static ConcurrentHashMap<Serializable, Timer> monitorRuleTimeAlert = new ConcurrentHashMap<>();

    @Data
    static class Timer {
        private Long lastAlarmTime;
    }

    /**
     * 检测是否可以告警
     * todo 收敛
     */
    private static boolean isTime2Alert(@NonNull MonitorRule monitorRule) {
        Timer getById = monitorRuleTimeAlert.get(monitorRule.getId());
        if (getById == null) {
            Timer timer = new Timer();
            timer.setLastAlarmTime(System.currentTimeMillis());
            monitorRuleTimeAlert.put(monitorRule.getId(), timer);
            return true;
        } else {
            Long aLong = getById.getLastAlarmTime();
            long now = System.currentTimeMillis();
            if (now - getById.getLastAlarmTime() >= aLong) {
                getById.setLastAlarmTime(System.currentTimeMillis());
                return true;
            }
            return false;
        }
    }

    /**
     * 默认20s一次
     */
    private void init() {
        scheduledFutureComponent.create("checkRecover", new CronTrigger("0/10 * * * * ? "), () -> {
            try {
                // TODO: 2020/11/12 优化 存到缓存中，只有修改 MonitorRule 才更新
                List<MonitorRule> monitorRuleList = monitorRuleService.list(new QueryWrapper<MonitorRule>().lambda()
                        .eq(MonitorRule::getIsAlert, true));
                List<Alerts> alertList = PrometheusApiUtils.getAlertList();
                alertList.forEach(alerts -> monitorRuleList.forEach(s -> {
                    if (alerts.getLabels().getAlertname().equals(s.getRuleName())) {
                        if (isTime2Alert(s)) {
                            List<MonitorEmail> byRuleId = monitorEmailService.getByRuleId(s.getId());
                            // TODO: 2020/11/   12 多人发送邮件接口
                            byRuleId.forEach(b -> iMailService.sendHtmlMail(b.getEmail(), s.getSubjectInfo(alerts), s.getSimpleContextInfo(alerts)));
                        }
                    }
                }));
            } catch (Exception e) {
                log.error("告警通知错误：" + e.getMessage());
            }
        });
    }
}